#ifndef __BINARY_TREE__
#define __BINARY_TREE__

template <typename T, template<typename> class P>
struct BinaryTree {
    using Value = T;
    using Pointer = P<BinaryTree<T, P>>;

    Value value;
    Pointer left;
    Pointer right;

    BinaryTree(const Value& value = Value(),
            Pointer left = Pointer(),
            Pointer right = Pointer()) :
        value(value), left(left), right(right) 
    { }

    BinaryTree(Value&& value,
            Pointer left = Pointer(),
            Pointer right = Pointer()) :
        value(std::move(value)), left(left), right(right) 
    { }
};

template <typename T>
struct BinaryTreeWithBarePointer {
    using Value = T;
    using Pointer = BinaryTreeWithBarePointer<T>*;

    Value value;
    Pointer left;
    Pointer right;

    BinaryTreeWithBarePointer(const Value& value, 
            Pointer left = Pointer(), 
            Pointer right = Pointer()) :
        value(value), left(left), right(right) 
    { }

    BinaryTreeWithBarePointer(Value&& value, 
            Pointer left = Pointer(), 
            Pointer right = Pointer()) :
        value(std::move(value)), left(left), right(right) 
    { }
};

#endif
